Loki de Grafana Labs ha ganado terreno como alternativa a Elasticsearch para logs. Su promesa — “como Prometheus pero para logs” — es atractiva: solo indexar labels, no el contenido, reduciendo brutalmente el coste de storage e indexing. Funciona muy bien para equipos medianos. A gran escala, los compromisos se notan. Este artículo recoge lecciones de operar Loki con volúmenes reales (>1TB/día) y los patrones que evitan dolores.
El modelo Loki en 30 segundos
Loki indexa solo labels (key-value pairs como {app="api", env="prod"}) y almacena el chunk de logs sin indexar en un object store (S3, GCS, MinIO). Las queries filtran primero por labels, luego escanean los chunks resultantes con regex/filtros.
Ventajas:
- Storage barato (S3 + compresión).
- Ingestión rápida — no hay pipeline de parsing pesado.
- Labels compatibles con Prometheus.
Límites:
- Queries no-label sobre mucho volumen son lentas.
- Cardinalidad de labels es el coste: cada combinación única genera un stream.
Cardinalidad: el asesino silencioso
El error más común es labels de alta cardinalidad. Ejemplos malos:
user_idcomo label (millones de valores).request_id(único por request).timestampo tiempo cualquiera.urlcompleta sin normalizar.
Cada valor único genera un stream. 10k usuarios × 5 entornos × 3 servicios = 150k streams activos. El índice se infla, las queries se degradan, el coste de object store se dispara por tanto fichero pequeño.
Regla de oro: labels para lo que filtras (app, env, cluster, severity, tenant si son pocos). Contenido para lo que buscas (user_id en el mensaje, consultable con regex).
Diseño de labels sano
Patrón práctico para equipos medianos:
{app, env, cluster, component}— eje fijo. 50-500 combinaciones típicas.{level}— log level (info/warn/error).- NO IDs únicos.
- NO valores libres del usuario.
Con este esquema, un entorno típico de 50 servicios × 3 environments × 2 clusters × 5 components × 4 levels = 6000 streams. Manejable.
Retention y compaction
Por defecto Loki guarda todo. En volumen grande, costoso y lento. Políticas típicas:
- 30-90 días para logs generales.
- 1 año para logs de auditoría/seguridad.
- Archivo frío a S3 Glacier tras N días si hay compliance.
Retention se configura por tenant o por label en la config. Importante: Loki compacta chunks periódicamente — planificar I/O y CPU para eso.
Separar read y write paths
En escala seria, no tener un mismo proceso gestionando ingest y queries. El diseño recomendado:
- Distributor + Ingester: pipeline de escritura. Recibe logs de Promtail/Alloy, los buffer en memoria, los escribe a object store en chunks.
- Querier + Query-frontend: pipeline de lectura. Paraleliza queries, cache, enviá resultados.
- Compactor: proceso batch para compactar chunks.
- Ruler: evalúa reglas de alerta sobre logs.
- Index Gateway: si usas boltdb-shipper o TSDB, sirve el índice a queries sin fricción.
Una query gorda no debe saturar la ingesta.
Promtail → Alloy
Promtail era el shipper tradicional. Grafana Alloy (antes Grafana Agent) lo reemplaza con un único agente que ships logs, metrics y traces. Para deployments nuevos, Alloy es la recomendación.
Config típica:
loki.source.file "logs" {
targets = [{__path__ = "/var/log/app/*.log"}]
forward_to = [loki.process.parse.receiver]
}
loki.process "parse" {
forward_to = [loki.write.default.receiver]
stage.regex {
expression = `level=(?P<level>\w+)`
}
stage.labels {
values = { level = "" }
}
}
loki.write "default" {
endpoint {
url = "https://loki.example.com/loki/api/v1/push"
}
}
Menos magia, más explícito que Promtail.
Storage: elegir bien
Para hobby o <100GB/día: single-binary Loki en un VM con disco local funciona. Para escala real:
- Object storage: S3 (o compatible: MinIO, Wasabi, Cloudflare R2). Cheap + infinitamente escalable.
- Indice: tsdb o boltdb-shipper. TSDB es el moderno.
- Cache: Memcached o Redis para query results y chunks frecuentes.
La distribución multi-zonal o multi-región depende del object store elegido.
Queries LogQL: patrones útiles
LogQL es el query language. Ejemplos de los que más uso real hacemos:
# Top errores por servicio en 1h
sum by (app) (count_over_time({env="prod", level="error"}[1h]))
# Latencia extraída de logs (requiere stage de parseo)
histogram_quantile(0.95,
sum by (le) (rate(
{app="api"}
| json
| unwrap duration
| __error__=""
[5m]
))
)
# Buscar patrón en una ventana
{app="api", env="prod"} |= "payment failed" | json | user_id = "12345"
Queries eficientes siempre empiezan con label matcher selectivo.
Alertas sobre logs
Loki soporta reglas Prometheus-style sobre métricas extraídas de logs:
groups:
- name: api-errors
rules:
- alert: HighErrorRate
expr: |
sum by (app) (rate({env="prod", level="error"}[5m])) > 10
for: 10m
labels:
severity: warning
annotations:
summary: "High error rate on {{ $labels.app }}"
Esto convierte a Loki en herramienta de alerting también. No tiene todo el rango de Elasticsearch/Kibana, pero cubre el 80%.
Cuándo Loki NO es la herramienta
Ser honesto:
- Búsqueda full-text sofisticada: Elasticsearch gana.
- Análisis forense profundo: Splunk, ElasticSearch tienen herramientas específicas.
- Compliance estricto con auditoría integrada: Splunk Enterprise está hecho para eso.
- Volumen masivo con necesidad de queries ad-hoc rápidas sobre mucho tiempo: Loki empieza a sufrir.
Loki es excelente para “monitoring-grade logs” — logs ingestados y consultados rutinariamente con patrones. Para “investigación profunda de pasado profundo”, hay opciones mejores.
Lecciones operacionales
Un año operando Loki serio deja:
- Cardinalidad explosiva es el incidente #1. Reviewar nuevos labels antes de merge.
- Query cap y timeouts: un user loco puede tumbar el cluster con una query mala.
- Backup del object store — la gente olvida que perder el bucket es perder todo.
- Monitorear Loki con Loki es circular — usar Prometheus + métricas de Loki.
- Rate limiting en ingesta por tenant — un servicio que spamea no debe afectar a los demás.
Conclusión
Loki es una elección sólida para logs en la mayoría de contextos cloud-native. Su diseño basado en labels ofrece ventajas enormes pero requiere disciplina — cardinalidad mal gestionada arruina la experiencia. A escala seria, separar read/write paths, invertir en cache y compactación, y elegir bien el object store son claves. Saber cuándo no es la herramienta correcta también es importante: para búsqueda forense profunda hay alternativas mejores. Para equipos que ya tienen Prometheus + Grafana, completar con Loki es de los cambios con mejor retorno en observabilidad.
Síguenos en jacar.es para más sobre observabilidad, Grafana stack y logs a escala.